#pragma once
#include <iostream>
#include <pthread.h>
#include <string>
#include <functional>
#include <string>
#include <cstring>
#include <errno.h>

template<class T>
using func_t = std::function<void(T)>;

template<class T>
class Thread
{
public:
    //初始化线程对象
    Thread(const std::string& pthreadName, func_t<T> func, T data)
    :_pthreadName(pthreadName), _func(func), _data(data)
    {}

    //线程函数
    static void* ThreadRoutine(void* args)
    {
        Thread* tc = static_cast<Thread*>(args);
        tc->_func(tc->_data);
        return nullptr;
    }
    //启动线程
    bool Start()
    {
        int ret = pthread_create(&_tid, nullptr, ThreadRoutine, this);
        if(ret == 0)
        {
            _isrunning = true;
            std::cout << _pthreadName << "线程启动成功" << std::endl;
            return true;
        }
        else
        {
            std::cout << strerror(errno) << std::endl;
            return false;
        }
    }

    //线程等待函数
    bool Join()
    {
        int ret = pthread_join(_tid, nullptr);
        if(ret == 0)
        {
            _isrunning = false;
            std::cout << _pthreadName << "Join成功, 线程结束" << std::endl;
            return true;
        }
        else
        {
            std::cout << strerror(errno) << std::endl;
            return false;
        }
    }
    
    //应对没有线程等待的情况
    ~Thread()
    {
        if(_isrunning == true)
        {
            pthread_cancel(_tid);
            pthread_join(_tid, nullptr);
        }
    }
private:
    pthread_t _tid;   //线程号
    const std::string _pthreadName;  //线程名称
    func_t<T> _func;     //线程要执行的函数
    bool _isrunning;  //线程是否在运行
    T _data;          //线程传的数据
};


//pthread_create要传递的线程函数，在Thread类里面实现（ThreadRoutine）,在线程函数内部在调用我们需要实现的函数
